package org.activequant.core.domainmodel.index;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import org.activequant.core.domainmodel.InstrumentSpecification;
import org.activequant.core.types.TimeStamp;
import org.activequant.util.tools.IdentityUtils;

/**
 * Class that describes a composition of stock index (like SP500 or Dow Jones).
 * Index identity is specified by instrumentSpecification (e.g.
 * InstrumentSpecification with name "SP500"). As index composition may vary
 * with time, index may have many IndexComposition instances. TimeStamp
 * property defines when this composition came into effect. From a time series
 * of IndexComposition objects (a list sorted by ascending timeStamp), and time
 * series of components (on the given scale) one can compute the index value by
 * aggregating component price.
 * <p>
 * Business keys for this object are:
 * <ul>
 * <li>instrumentSpecification</li>
 * <li>timeStamp</li>
 * </ul>
 * A final class. Holds the following associated variables:
 * <ul>
 * <li>id(Long)</li>
 * <li>spec(InstrumentSpecification)</li>
 * <li>timeStamp(TimeStamp)</li>
 * <li>components(Set&lt;IndexComponent&gt;)</li>
 * </ul>
 * <br>
 * <b>History:</b><br>
 * - [08.06.2008] Created (Mike Kroutikov)<br>
 * 
 * @author Mike Kroutikov
 * @author Wessel de Roode
 * @author SandhuQ
 * 
 */
public final class IndexComposition implements Serializable, Comparable<IndexComposition> {
	private static final long serialVersionUID = -1307170244642139344L;
	/**
	 * private Long id;
	 */
	private Long id;
	/**
	 * private InstrumentSpecification spec;
	 */
	private InstrumentSpecification spec;
	/**
	 * private TimeStamp timeStamp;
	 */
	private TimeStamp timeStamp;
	/**
	 * private Set&lt;IndexComponent&gt; components = new HashSet&lt;IndexComponent&gt;();
	 */
	private Set<IndexComponent> components = new HashSet<IndexComponent>();
	/**
	 * returns the associated id(Long)
	 * @return
	 */
	public Long getId() {
		return id;
	}
	/**
	 * sets the associated id(Long) with the given val(Long)
	 * @param val
	 */
	public void setId(Long val) {
		id = val;
	}
	/**
	 * returns the associated spec(InstrumentSpecification)
	 * @return
	 */
	public InstrumentSpecification getInstrumentSpecification() {
		return spec;
	}
	/**
	 * sets the associated spec(InstrumentSpecification) with the given val(InstrumentSpecification)
	 * @param val
	 */
	public void setInstrumentSpecification(InstrumentSpecification val) {
		spec = val;
	}
	/**
	 * returns the associated timeStamp(TimeStamp)
	 * @return
	 */
	public TimeStamp getTimeStamp() {
		return timeStamp;
	}
	/**
	 * sets the associated timeStamp(TimeStamp) with the given val(TimeStamp)
	 * @param val
	 */
	public void setTimeStamp(TimeStamp val) {
		timeStamp = val;
	}
	/**
	 * returns the associated components(Set&lt;IndexComponent&gt;)
	 * @return
	 */
	public Set<IndexComponent> getComponents() {
		return components;
	}
	/**
	 * sets the associated components(Set&lt;IndexComponent&gt;) with the given val(Set&lt;IndexComponent&gt;)
	 * @param val
	 */
	public void setComponents(Set<IndexComponent> val) {
		components = val;
	}

	public int compareTo(IndexComposition o) {
		int rc;

		if ((rc = IdentityUtils.safeCompare(spec, o.spec)) != 0) {
			return rc;
		}
		if ((rc = IdentityUtils.safeCompare(timeStamp, o.timeStamp)) != 0) {
			return rc;
		}

		return 0;
	}

	@Override
	public int hashCode() {
		return IdentityUtils.safeHashCode(spec) + IdentityUtils.safeHashCode(timeStamp);
	}

	@Override
	public boolean equals(Object other) {
		return IdentityUtils.equalsTo(this, other);
	}
	/**
	 * returns a String in the form: "${getClass.getSimpleName}{spec=${spec}, timeStamp=${timeStamp}}"
	 */
	@Override
	public String toString() {
		return getClass().getSimpleName() + "{spec=" + spec + ", timeStamp=" + timeStamp + "}";
	}
}
